﻿using System.ComponentModel;
using ValidationEngine.Commons.Enums;
using DevExpress.XtraEditors.DXErrorProvider;
using ValidationEngine.Commons.Interfaces;

namespace ValidationEngine.Commons
{
    /// <summary>
    /// Basic IValidateableModel interface implementation.
    /// </summary>
    public class ValidateableModel: INotifyPropertyChanged, IDataErrorInfo, IValidateableModel, IDXDataErrorInfo        
    {
        #region Members
        /// <summary>
        /// Stores model validation information
        /// </summary>
        private ModelValidationProperties _validationProperties;

        /// <summary>
        /// Notifies about model's property value changed
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;
        /// <summary>
        /// Implemnt property validation from external code
        /// </summary>
        event PropertyValidationEventHandler IValidateableModel.PropertyValidating
        {
            add 
            {
                _validationProperties.PropertyValidating += value;
            }
            remove
            {
                _validationProperties.PropertyValidating -= value;
            }
        }
        /// <summary>
        /// fake id
        /// </summary>
        private static long lastId = -1;

        #endregion

        #region Ctor
        protected ValidateableModel()
        {
            this._validationProperties = new ModelValidationProperties(this);
        }
        #endregion

        #region INotifyPropertyChanged
        /// <summary>
        /// Raises PropertyChanged event after ValidatingProperty is raised
        /// </summary>
        /// <param name="propName">Property name</param>
        protected virtual void OnChanged(string propName)
        {
            RaiseValidateProperty(propName);
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }

        protected void RaiseValidateProperty(string propName)
        {
            _validationProperties.RaiseValidateProperty(propName);
        }
        #endregion

        #region IDataErrorInfo
        [Browsable(false)]
        public string Error
        {
            get { return null; }
        }

        public string this[string propertyName]
        {
            get
            {
                return _validationProperties.GetCachedPropertyValidation(propertyName);
            }
        }
        #endregion

        #region IDXDataErrorInfo
        public void GetError(ErrorInfo info)
        {
        }

        public void GetPropertyError(string propertyName, ErrorInfo info)
        {
            _validationProperties.GetPropertyError(propertyName, info);
        }
        #endregion

        #region IValidateableModel
        void IValidateableModel.ClearPropertyValidationInfo(string propertyName)
        {
            _validationProperties.ClearPropertyValidationInfo(propertyName);
        }

        void IValidateableModel.SetPropertyValidationInfo(string propertyName, IValidationInfo info)
        {
            _validationProperties.SetPropertyValidationInfo(propertyName, info);
        }

        IValidationInfo IValidateableModel.GetPropertyValidationInfo(string propertyName)
        {
            return _validationProperties.GetPropertyValidationInfo(propertyName);
        }

        void IValidateableModel.ReValidate(RuleApplingContext ctx)
        {
            _validationProperties.ReValidate(ctx);
        }

        void IValidateableModel.ClearAllValidations()
        {
            _validationProperties.ClearValidationsInfo();
        }

        public bool IsValid
        {
            get { return _validationProperties.IsValid; }
        }
        #endregion

        protected static long GetNewId()
        {
            return --lastId;
        }
    }
}
